﻿using System;
using System.Collections.Generic;
using HollyInfo.Hiris;

namespace Hollysys.MES.Common.Rmis
{
    public class RmisDataReader : IDisposable
    {
        #region 成员变量
        /// <summary>
        /// RMIS数据库连接字符串
        /// </summary>
        private string m_connectionString;
        /// <summary>
        /// Server
        /// </summary>
        private Server m_svr = null;
        /// <summary>
        /// DataReader
        /// </summary>
        private DataReader m_dr = null;
        /// <summary>
        /// 当前连接状态
        /// </summary>
        private bool m_isOpened = false;
        /// <summary>
        /// 小数位数
        /// </summary>
        private int m_decimals = 3;
        #endregion 成员变量

        #region 属性
        /// <summary>
        /// 当前连接状态
        /// </summary>
        public bool IsOpened
        {
            get { return m_isOpened; }
            set { m_isOpened = value; }
        }
        #endregion 属性

        #region 构造
        /// <summary>
        /// 构造
        /// </summary>
        /// <param name="connectionString">RMIS连接字符串</param>
        public RmisDataReader(string connectionString)
        {
            if (!String.IsNullOrEmpty(connectionString) && connectionString.Trim().Length > 0)
            {
                m_connectionString = connectionString;
            }
            else
            {
                throw new ArgumentException("RMIS连接字符串不能为空", "connectionString");
            }
        }
        /// <summary>
        /// 构造
        /// </summary>
        /// <param name="connectionString">RMIS数据库连接字符串</param>
        /// <param name="decimals">小数位</param>
        public RmisDataReader(string connectionString, int decimals)
            : this(connectionString)
        {
            if (decimals < 0)
            {
                decimals = 0;
            }
            m_decimals = decimals;
        }
        #endregion 构造

        #region 方法

        #region 打开关闭

        /// <summary>
        /// 打开实时库连接
        /// </summary>
        /// <returns>是否连接成功</returns> 
        public bool Open()
        {
            if (!m_isOpened)
            {
                try
                {//连接
                    if (m_svr == null)
                    {
                        m_svr = new Server();
                    }
                    m_svr.Open(m_connectionString);
                }
                catch (Exception ex)
                {
                    throw new Exception("连接RMIS错误", ex);
                }

                try
                {
                    if (m_dr == null)
                    {
                        m_dr = new DataReader(m_svr);
                    }
                    m_isOpened = true;
                }
                catch (Exception ex)
                {
                    throw new Exception("打开RMIS错误", ex);
                }
                finally
                {
                    if (!m_isOpened)
                    {
                        m_svr.Close();
                    }
                }
            }

            return m_isOpened;
        }

        /// <summary>
        /// 关闭实时库连接
        /// </summary>
        /// <returns></returns>
        public void Close()
        {
            if (m_svr != null)
            {
                m_svr.Close();
                m_isOpened = false;
            }
        }

        #endregion 打开关闭

        #region 读取当前数据

        /// <summary>
        /// 获取指定位号当前值
        /// </summary>
        /// <param name="tag">位号</param>
        /// <returns></returns>
        public string GetCurrentDataValue(string tag)
        {
            return GetCurrentDataValue(false, tag);
        }

        /// <summary>
        /// 获取指定位号当前值
        /// </summary>
        /// <param name="checkClctTimeout">是否检查采集器超时</param>
        /// <param name="tag">位号</param>
        /// <returns></returns>
        public string GetCurrentDataValue(bool checkClctTimeout, string tag)
        {
            string _result = String.Empty;
            if (String.IsNullOrEmpty(tag) || tag.Trim().Length == 0)
            {
                throw new ArgumentNullException("tag", "点名不能为空");
            }

            try
            {
                IDictionary<string, string> _data = GetCurrentDataValues(checkClctTimeout, tag);

                _data.TryGetValue(tag.Trim(), out _result);

            }
            catch (Exception ex)
            {
                throw new Exception(String.Format("读取位号:{0},数据错误，请检查RMIS是否已连接(open方法是否在之前调用).", tag), ex);
            }

            return _result;
        }
        /// <summary>
        /// 获取一组位号当前数据
        /// </summary>
        /// <param name="checkClctTimeout">是否检查采集器超时</param>
        /// <param name="tags">至少需要一个位号</param>
        /// <returns></returns>
        public IDictionary<string, string> GetCurrentDataValues(bool checkClctTimeout, params string[] tags)
        {
            if (tags == null || tags.Length < 1)
            {
                throw new ArgumentNullException("tags", "至少需要一个位号.");
            }

            IDictionary<string, string> _result = new Dictionary<string, string>();

            //检查位号
            List<string> _keys = new List<string>();
            foreach (string tag in tags)
            {
                if (!String.IsNullOrWhiteSpace(tag) && !_keys.Contains(tag.Trim()))
                {
                    _keys.Add(tag.Trim());
                }
            }
            if (_keys.Count < 1)
            {
                throw new ArgumentNullException("tags", "至少需要一个不为空的位号.");
            }


            try
            {
                //读取数据
                Data[] _data = m_dr.ReadCurrent(_keys.ToArray(), checkClctTimeout);
                //整理结果
                if (_data != null && _data.Length > 0)
                {
                    for (int i = 0; i < _data.Length; i++)
                    {
                        _result.Add(_keys[i], _data[i].Value.ToString());
                    }
                }
            }
            catch (Exception ex)
            {
                throw new Exception("读取数据错误，请检查RMIS是否已连接(open方法是否在之前调用).", ex);
            }

            return _result;
        }
        #endregion 读取当前数据

        #region 读取历史数据
        /// <summary>
        /// 获取历史数据
        /// </summary>
        /// <param name="dtime">时间</param>
        /// <param name="tag">位号</param>
        /// <returns>返回历史数据</returns>
        public string GetHistoryDataValue(DateTime dtime, string tag)
        {
            string dValue = null;
            if (String.IsNullOrWhiteSpace(tag))
            {
                throw new ArgumentNullException("tag", "位号不能为空.");
            }
            if (dtime > DateTime.Now)
            {
                throw new ArgumentOutOfRangeException("dtime", dtime, "不能晚于当前系统时间.");
            }

            try
            {
                DateTime utcTime = dtime.ToUniversalTime();
                Data[] data = m_dr.ReadHistory(tag, SampleMode.Raw, utcTime.AddSeconds(-1800), utcTime, TimeSpan.FromMilliseconds(1000));

                if (data.Length == 0)
                {
                    data = m_dr.ReadHistory(tag, SampleMode.Stepped, utcTime.AddHours(-1), utcTime.AddSeconds(1), TimeSpan.FromMilliseconds(1800000));
                }

                if (data.Length > 0)
                {
                    //得到值
                    dValue = data[data.Length - 1].Value.ToString();
                }
            }
            catch (Exception ex)
            {
                throw new Exception(String.Format("读取位号:{0},数据错误，请检查RMIS是否已连接(open方法是否在之前调用).", tag), ex);
            }

            return dValue;
        }

        /// <summary>
        /// 获取历史数据
        /// </summary>
        /// <param name="dtime">时间</param>
        /// <param name="tags">至少需要一个位号</param>
        /// <returns>返回历史数据集合</returns>
        public IDictionary<string, string> GetHistoryDataValues(DateTime dtime, params string[] tags)
        {
            if (tags == null || tags.Length < 1)
            {
                throw new ArgumentNullException("tags", "至少需要一个位号.");
            }

            IDictionary<string, string> _result = new Dictionary<string, string>();

            //检查位号
            List<string> _keys = new List<string>();
            foreach (string tag in tags)
            {
                if (String.IsNullOrWhiteSpace(tag))
                {
                    continue;
                }

                string _key = tag.Trim();

                //过滤重复位号
                if (!_result.ContainsKey(_key))
                {
                    _result.Keys.Add(tag.Trim());
                }
                else
                {
                    continue;
                }

                //读取值
                try
                {
                    string _vlu = GetHistoryDataValue(dtime, tag.Trim());
                    _result[_key] = _vlu;
                }
                catch
                {
                    continue;
                }
            }
            if (_result.Keys.Count < 1)
            {
                throw new ArgumentNullException("tags", "至少需要一个不为空的位号.");
            }

            return _result;
        }
        #endregion 读取历史数据

        #endregion 方法

        #region IDisposable
        /// <summary>
        /// 释放资源
        /// </summary>
        public void Dispose()
        {
            if (m_svr != null && m_isOpened)
            {
                m_svr.Close();
                m_svr.Dispose();
            }
        }
        #endregion IDisposable

    }
}
